package com.unitd.base.frame.plugin.db.datasource.config;

import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.unitd.base.frame.plugin.db.datasource.context.DataSourceContext;
import com.unitd.base.frame.plugin.db.datasource.context.SqlSessionFactoryContext;
import com.unitd.base.frame.plugin.db.datasource.context.SqlSessionFactoryCreator;
import com.unitd.base.frame.plugin.db.datasource.mybatis.OptionalSqlSessionTemplate;
import com.unitd.base.frame.plugin.db.datasource.properties.DruidProperties;
import com.unitd.base.frame.plugin.db.enums.DataSourceErrorEnum;
import com.unitd.base.frame.plugin.db.exception.DataSourceException;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;

/**
 * 多数据源配置
 * 注：由于引入多数据源，所以让spring事务的aop要在多数据源切换aop的后面
 *
 * @author Hudan
 * @version 1.0
 * @filename SqlSessionFactoryConfig.java
 * @copyright www.unitd.com
 * @date 2020-06-28
 */
@Slf4j
@Configuration
@Import(SqlSessionFactoryCreator.class)
public class SqlSessionFactoryConfig {

    /**
     * 创建主数据源的 sqlSessionFactory
     *
     * @param dataSource               数据源对象
     * @param sqlSessionFactoryCreator 数据库操作句柄创建者
     * @return 数据库操作句柄
     */
    @Primary
    @Bean
    public SqlSessionFactory sqlSessionFactoryPrimary(@Qualifier("dataSourcePrimary") DataSource dataSource,
                                                      SqlSessionFactoryCreator sqlSessionFactoryCreator) {
        return sqlSessionFactoryCreator.createSqlSessionFactory(dataSource);
    }

    /**
     * 多数据源sqlSessionTemplate切换模板
     *
     * @param dataSourcePrimary        主数据源
     * @param sqlSessionFactoryPrimary 主数据源数据库操作句柄
     * @param sqlSessionFactoryCreator 数据库操作句柄创建者
     * @param druidProperties          Druid插件配置参数
     * @return 多数据源sqlSessionTemplate切换模板
     */
    @Bean(name = "unitdSqlSessionTemplate")
    public OptionalSqlSessionTemplate unitdSqlSessionTemplate(@Qualifier("dataSourcePrimary") DataSource dataSourcePrimary,
                                                             @Qualifier("sqlSessionFactoryPrimary") SqlSessionFactory sqlSessionFactoryPrimary,
                                                             SqlSessionFactoryCreator sqlSessionFactoryCreator,
                                                             DruidProperties druidProperties) {
        // 初始化数据源容器
        try {
            DataSourceContext.initDataSource(druidProperties, dataSourcePrimary);
        } catch (Exception e) {
            log.error("初始化数据源容器错误!", e);
            throw new DataSourceException(DataSourceErrorEnum.INIT_DATA_SOURCE_ERROR);
        }

        // 添加主数据源的SqlSessionFactory
        SqlSessionFactoryContext.addSqlSessionFactory(DataSourceContext.MASTER_DATASOURCE_NAME, sqlSessionFactoryPrimary);

        // 初始化其他数据源的SqlSessionFactory的容器
        SqlSessionFactoryContext.initBaseSqlSessionFactory(sqlSessionFactoryCreator);

        // 设置SqlHelper为主数据源
        SqlHelper.FACTORY = sqlSessionFactoryPrimary;

        return new OptionalSqlSessionTemplate(sqlSessionFactoryPrimary, SqlSessionFactoryContext.getSqlSessionFactorys());
    }
}